package com.nykredit.kundeservice.swing.components;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import org.joda.time.Chronology;
import org.joda.time.DateTimeConstants;
import org.joda.time.DateTimeField;
import org.joda.time.LocalDate;
import org.joda.time.chrono.ISOChronology;
import com.nykredit.kundeservice.awt.PrintComp;
import com.nykredit.kundeservice.data.DopeDBException;
import com.nykredit.kundeservice.data.DopeException;
import com.nykredit.kundeservice.data.KSDriftConnection;
import com.nykredit.kundeservice.data.sql.OracleFormats;
import com.nykredit.kundeservice.data.sql.SqlQuery;
import com.nykredit.kundeservice.util.OperationAbortedException;
public class CalendarPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<LocalDate> kundeserviceOpenDates = new ArrayList<LocalDate>();
private ArrayList<DateLabel> labels;
private JLabel titleLabel = new JLabel();
private final JPanel calendarPanel = new JPanel();
private HashMap<String, CalendarMarkings> markings = new HashMap<String, CalendarMarkings>();
private LocalDate startOfCalendar;
private LocalDate endOfCalendar;
private boolean lockServiceCenterClosedDateLabels = true;
private Color colorOfServiceCenterClosedDateLabels = new Color(165,191,225);
public LocalDate getStartOfCalendar(){
return this.startOfCalendar;
}
public void setStartOfCalendar(LocalDate startOfCalendar){
if(startOfCalendar == null)
throw new IllegalArgumentException("Start of Calendar cannot be null");
else if(this.endOfCalendar.isBefore(startOfCalendar))
throw new IllegalArgumentException("Start of Calendar must be before end of Calendar");
this.startOfCalendar = startOfCalendar;
}
public void setTitle(String title){
this.titleLabel.setText(title);
if(title == null || title.equals(""))
this.setTitleVisible(false);
}
public String getTitle(){
return this.titleLabel.getText();
}
public void setTitleVisible(boolean titleVisible){
this.titleLabel.setVisible(titleVisible);
}
public boolean getTitleVisible(){
return this.titleLabel.isVisible();
}
public LocalDate getEndOfCalendar(){
return this.endOfCalendar;
}
public void setEndOfCalendar(LocalDate endOfCalendar){
if(endOfCalendar == null)
throw new IllegalArgumentException("End of Calendar cannot be null");
else if(this.startOfCalendar.isAfter(endOfCalendar))
throw new IllegalArgumentException("End of Calendar must be after start of Calendar");
this.endOfCalendar = endOfCalendar;
}
public boolean getLockServiceCenterClosedDateLabels(){
return this.lockServiceCenterClosedDateLabels;
}
public void setLockServiceCenterClosedDateLabels(boolean lockServiceCenterClosedDateLabels){
this.lockServiceCenterClosedDateLabels = lockServiceCenterClosedDateLabels;
}
public void setKundeserviceOpenDates(ArrayList<LocalDate> kundeserviceOpenDates){
this.kundeserviceOpenDates = kundeserviceOpenDates;
}
public ArrayList<LocalDate> getKundeserviceOpenDates(){
return this.kundeserviceOpenDates;
}
public CalendarPanel(){
this.startOfCalendar = ((new LocalDate()).minusMonths(12));
this.endOfCalendar = new LocalDate();
this.basicSetup();
}
public CalendarPanel(String title, LocalDate startOfCalendar, LocalDate endOfCalendar){
this.setTitle(title);
this.startOfCalendar = startOfCalendar;
this.endOfCalendar = endOfCalendar;
this.basicSetup();
}
private void basicSetup(){
this.setLayout(new BorderLayout());
this.setBackground(Color.WHITE);
this.calendarPanel.setBackground(Color.WHITE);
this.add(this.titleLabel, BorderLayout.NORTH);
this.add(this.calendarPanel, BorderLayout.CENTER);
this.titleLabel.setFont(new Font("Tahoma", Font.BOLD, 16));
this.titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
this.updateCalendar();
}
public void addCalendarMarking(String id, CalendarMarkings marking){
this.markings.put(id, marking);
}
public void removeCalendarMarking(String id){
this.markings.remove(id);
}
public void clearCalendarMarkings(){
this.markings.clear();
}
public void updateCalendar(){
this.calendarPanel.removeAll();
this.labels = new ArrayList<DateLabel>();
this.calendarPanel.setLayout(new GridBagLayout());
LocalDate dateIterator = this.startOfCalendar;
LocalDate sentinel = this.endOfCalendar.plusDays(1);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.gridx = 0;
c.gridy = 0;
if(dateIterator.getDayOfMonth() > 1)
this.calendarPanel.add(new MonthLabel(dateIterator, true), c);
c.gridy += 1;
if(dateIterator.getDayOfMonth() > 1){
c.gridheight = this.startOfCalendar.getDayOfMonth() - 1;
c.fill = GridBagConstraints.VERTICAL;
this.calendarPanel.add(new EmptyLabel(this.startOfCalendar.getDayOfMonth() - 1), c);
c.gridheight = 1;
c.gridy += this.startOfCalendar.getDayOfMonth() - 2;
}
while(dateIterator.isBefore(sentinel)){
if(dateIterator.getDayOfMonth() == 1){
c.gridy = 0;
if(!this.startOfCalendar.equals(dateIterator))
c.gridx += 1;
this.calendarPanel.add(new MonthLabel(dateIterator, false));
}
c.gridy += 1;
boolean serviceCenterOpenOnDate = this.isDateWorkDay(dateIterator);
this.calendarPanel.add(new DateLabel(dateIterator,
(serviceCenterOpenOnDate ? Color.WHITE : this.colorOfServiceCenterClosedDateLabels),
(this.lockServiceCenterClosedDateLabels ? !serviceCenterOpenOnDate : false)),
c);
dateIterator = dateIterator.plusDays(1);
}
c.gridy += 1;
c.fill = GridBagConstraints.VERTICAL;
c.gridheight = this.getDaysInMonth(dateIterator) - c.gridy + 1;
this.calendarPanel.add(new EmptyLabel(this.getDaysInMonth(dateIterator) - c.gridy + 1), c);
this.updateMarkings();
}
public void updateMarkings(){
Iterator<Entry<String, CalendarMarkings>> it = this.markings.entrySet().iterator();
for(DateLabel l : this.labels)
if(l.getLabelLocked() == false)
l.setLabelColor(Color.WHITE);
while (it.hasNext()) {
Map.Entry<String, CalendarMarkings> pairs = (Map.Entry<String, CalendarMarkings>)it.next();
for(LocalDate c : pairs.getValue().getDates()){
for(DateLabel l : this.labels){
if(l.getLabelDate().toDateMidnight().equals(c.toDateMidnight()) && !l.getLabelLocked())
l.setLabelColor(pairs.getValue().getColor());
}
}
}
}
public void LoadKundeserviceBusinessDates(KSDriftConnection conn) throws OperationAbortedException {
this.kundeserviceOpenDates = new ArrayList<LocalDate>();
SqlQuery query = new SqlQuery(conn,
"SELECT " +
"THIS_DATE " +
"FROM " +
"SYS_DATE_KS " +
"WHERE " +
"THIS_DATE >= " + OracleFormats.convertDate(this.startOfCalendar.toDate()) + " AND " +
"THIS_DATE <=" + OracleFormats.convertDate(this.endOfCalendar.toDate()));
try{
query.execute();
while (query.next()){
this.kundeserviceOpenDates.add(new LocalDate(query.getDate("THIS_DATE").toString()));
}
} catch (DopeException e) {
throw new OperationAbortedException(e, "Error occured while loading data from SYS_DATE", "Der skete en fejl ved indl�sning af �bningsdage i kundeservice.");
}
this.updateCalendar();
}
public void LoadKundeserviceBusinessDates() throws OperationAbortedException {
KSDriftConnection conn;
try {
conn = new KSDriftConnection();
} catch (DopeDBException e) {
throw new OperationAbortedException(e, "Couldnt connect to database.", "Kunne ikke oprette forbindelse til databasen.");
}
this.LoadKundeserviceBusinessDates(conn);
}
public void ClearKundeserviceOpenDates(){
this.kundeserviceOpenDates = new ArrayList<LocalDate>();
}
public void PrintCalendar(String printerJobName){
boolean titleLabelIsShown = this.titleLabel.isVisible();
if(!this.titleLabel.getText().equals("") && !titleLabelIsShown)
this.titleLabel.setVisible(true);
PrintComp.printComponent(this, printerJobName);
if(!titleLabelIsShown)
this.titleLabel.setVisible(false);
}
private int getDaysInMonth(LocalDate date){
Chronology chrono = ISOChronology.getInstance();
DateTimeField dayField = chrono.dayOfMonth();
LocalDate monthDate = new LocalDate(date.getYear(), date.getMonthOfYear(), 1);
return dayField.getMaximumValue(monthDate);
}
private class DateLabel extends JPanel{
private static final long serialVersionUID = 1L;
private LocalDate labelDate;
private boolean labelLocked = false;
private JLabel weekdayLetterLabel = new JLabel();
private JLabel dateLabel = new JLabel();
private JLabel dateNoteLabel = new JLabel();
public LocalDate getLabelDate(){
return this.labelDate;
}
public boolean getLabelLocked(){
return this.labelLocked;
}
public void setLabelLocked(boolean labelLocked){
this.labelLocked = labelLocked;
}
public Color getLabelColor(){
return this.weekdayLetterLabel.getBackground();
}
public void setLabelColor(Color labelColor){
this.weekdayLetterLabel.setBackground(labelColor);
this.dateLabel.setBackground(labelColor);
this.dateNoteLabel.setBackground(labelColor);
}
public DateLabel(LocalDate labelDate, Color labelColor, boolean locked){
if(labelDate == null)
throw new IllegalArgumentException("Label date cannot be null");
else if(labelColor == null)
throw new IllegalArgumentException("Label color cannot be null");
this.labelDate = labelDate;
this.labelLocked = locked;
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.BLACK));
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(0, 0, 0, 0);
this.weekdayLetterLabel.setMinimumSize(new Dimension(15, 15));
this.weekdayLetterLabel.setPreferredSize(new Dimension(15, 15));
this.weekdayLetterLabel.setOpaque(true);
this.weekdayLetterLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
this.weekdayLetterLabel.setHorizontalAlignment(JLabel.CENTER);
this.weekdayLetterLabel.setFont(new Font("Arial", Font.PLAIN, 11));
switch(labelDate.getDayOfWeek()){
case DateTimeConstants.MONDAY:
this.weekdayLetterLabel.setText("M");
break;
case DateTimeConstants.TUESDAY:
this.weekdayLetterLabel.setText("T");
break;
case DateTimeConstants.WEDNESDAY:
this.weekdayLetterLabel.setText("O");
break;
case DateTimeConstants.THURSDAY:
this.weekdayLetterLabel.setText("T");
break;
case DateTimeConstants.FRIDAY:
this.weekdayLetterLabel.setText("F");
break;
case DateTimeConstants.SATURDAY:
this.weekdayLetterLabel.setText("L");
break;
case DateTimeConstants.SUNDAY:
this.weekdayLetterLabel.setText("S");
break;
}
this.add(this.weekdayLetterLabel, c);
this.dateLabel.setMinimumSize(new Dimension(15, 15));
this.dateLabel.setPreferredSize(new Dimension(15, 15));
this.dateLabel.setOpaque(true);
this.dateLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
this.dateLabel.setHorizontalAlignment(JLabel.CENTER);
this.dateLabel.setFont(new Font("Arial", Font.PLAIN, 11));
this.dateLabel.setText(Integer.toString(labelDate.getDayOfMonth()));
this.add(this.dateLabel, c);
this.dateNoteLabel.setMinimumSize(new Dimension(60, 15));
this.dateNoteLabel.setPreferredSize(new Dimension(60, 15));
this.dateNoteLabel.setOpaque(true);
this.dateNoteLabel.setHorizontalAlignment(JLabel.RIGHT);
this.dateNoteLabel.setFont(new Font("Arial", Font.PLAIN, 11));
if(labelDate.getDayOfWeek() == DateTimeConstants.MONDAY)
this.dateNoteLabel.setText(Integer.toString(labelDate.getWeekOfWeekyear()));
this.add(this.dateNoteLabel, c);
this.setLabelColor(labelColor);
CalendarPanel.this.labels.add(this);
}
}
private boolean isDateWorkDay(LocalDate date){
if (this.kundeserviceOpenDates.size() == 0)
return true;
for(LocalDate d : this.kundeserviceOpenDates)
if(d.toDateMidnight().equals(date.toDateMidnight()))
return true;
return false;
}
private class EmptyLabel extends JLabel {
private static final long serialVersionUID = 1L;
public EmptyLabel(int numberOfRows){
this.setBackground(Color.LIGHT_GRAY);
this.setOpaque(true);
this.setMinimumSize(new Dimension(92, 15 * numberOfRows + numberOfRows));
this.setPreferredSize(new Dimension(92, 15 * numberOfRows + numberOfRows));
this.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.BLACK));
}
}
private class MonthLabel extends JLabel {
private static final long serialVersionUID = 1L;
public MonthLabel(LocalDate date, boolean includeYear){
this.setBackground(Color.BLACK);
this.setOpaque(true);
this.setMinimumSize(new Dimension(92, 15));
this.setPreferredSize(new Dimension(92, 15));
this.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
this.setHorizontalAlignment(JLabel.CENTER);
this.setFont(new Font("Arial", Font.PLAIN, 11));
this.setForeground(Color.WHITE);
String labelText = date.toString("MMMM");
if(includeYear || date.getMonthOfYear() == 1)
labelText += " " + date.toString("y");
this.setText(labelText);
}
}
public class CalendarMarkings{
private String description;
private LocalDate[] dates;
private Color color;
public String getDescription(){
return this.description;
}
public void setDescription(String description){
this.description = description;
}
public LocalDate[] getDates(){
return this.dates;
}
public void setDates(LocalDate[] dates){
this.dates = dates;
}
public Color getColor(){
return this.color;
}
public void setColor(Color color){
this.color = color;
}
public CalendarMarkings(String description, LocalDate[] dates, Color color){
if(description == null)
throw new IllegalArgumentException("Description cannot be null");
else if(dates == null)
throw new IllegalArgumentException("Dates cannot be null");
else if(color == null)
throw new IllegalArgumentException("Color cannot be null");
this.description = description;
this.dates = dates;
this.color = color;
}
}
}